﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Greedy
{
	//贪心算法
	/*
	 *  这个贪心的行为在算法中也成为了一种指导思想，也就是说贪心算法所作出的选择在当时的环境下是最好的，说深一点就是它只是某种意义上的局部最优解，但不一定是全局最优解，此时往往接近于最优解。
	 *  问题：
	 ① 不能保证贪心所得出的解是整体最优的。
     ② 不能用来求最大解和最小解问题。
     ③ 只能求满足某些约束条件的可行解的范围。
	 */
	class Program
	{
		static void Main(string[] args)
		{
			Console.Write("请输入余额：");
			var money = ExChange(decimal.Parse(Console.ReadLine()));
			Console.WriteLine("\n找给您的张数为：\n");
			foreach (var single in money)
			{
				if (single.Value != 0)
				{
					Console.WriteLine("{0}元\t{1}张\n", single.Key, single.Value);
				}
			}
			Console.WriteLine("--------------------------------------------------------------------");
			Console.ReadLine();
		}

		//案例
		/*
		 *  其实说到贪心，基本上都会提到“背包问题”，这里我就举一个“找零钱的问题“，对的，找零钱问题是我们生活中一个活生生的贪心算法的例子，比如我买了“康师傅来一桶方便面”，给了10两银子，方便面3.8两，那么收银mm该找我6.2两，现实中mm不自觉的就会用到贪心的行为给我找最少张币，总不能我给mm一张，mm给我十几张，那样mm会心疼的。此时mm提供的方案就是：5元1张，1元1张，2角1张。
		 */
		static Dictionary<decimal,int> ExChange(decimal num)
		{
			var money = GetInit();
			int i = 0;
			while (true)
			{
				if(num<0.05M)
				{
					return money;
				}
				var max = money.Keys.ElementAt(i);
				if(num>=max)
				{
					num = num - max;
					//money的张数自增
					money[max] = money[max] + 1;
				}
				else
				{
					//如果是小于1毛，大于5分的情况
					if(num<0.1M && num>=0.05M)
					{
						//按一毛计算
						money[0.10M] = money[0.10M] + 1;
						num = 0.0M;
					}
					else
					{
						i++;
					}
				}
			}
		}

		static Dictionary<decimal,int> GetInit()
		{
			Dictionary<decimal,int> money=new Dictionary<decimal, int>();
			money.Add(100.00M,0);
			money.Add(50.00M, 0);
			money.Add(20.00M, 0);
			money.Add(10.00M, 0);
			money.Add(5.00M, 0);
			money.Add(2.00M, 0);
			money.Add(1.00M, 0);
			money.Add(0.50M, 0);
			money.Add(0.20M, 0);
			money.Add(0.10M, 0);
			return money;
		}
	}
}
